#ifndef WORKFLOWXML_H
#define WORKFLOWXML_H

#include <QDateTime>
#include <QGraphicsItem>
#include <QString>
#include <QObject>
#include <QDomNodeList>
#include <QDebug>
#include <QFile>
#define GengeralStartIcon  ":/images/startstep.png";
#define GengeralEndIcon  ":/images/endstep.png";
#define GengeralRecycleIcon  ":/images/recyclestep.png";
#define GengeralConditionIcon  ":/images/conditionstep.png";
#define GengeralGeoIcon  ":/images/geostep.png";
#define GengeralMeshIcon  ":/images/meshstep.png";
#define GengeralSolverIcon  ":/images/solverstep.png";
#define GengeralPostIcon  ":/images/poststep.png";

#define XMLFilePath "../bin/xml/"
//#define StepCount 1000


enum Mode { InsertItem, InsertLine, MoveItem };

enum StepType{
    Start = QGraphicsLineItem::UserType+3,
    End,
    Loop,
    Condition,
    Geometry,
    Grid,
    Sover,
    BackDeal
};


struct CRelationProperty
{
    QString name;
    QString type;
};

struct CActionProperty
{
    QString name;
    QString script;
    QString command;
    QString type;

};
struct CActionParam
{
    QString name;
    QString refers;
    QString direction;
};


struct CStepProperty
{
    QString name;
    QString desp;
    int id;
    QString type;
    QPointF pos;
};
struct CStepParam
{
    QString name;
    QString desp;
    QString type;
    QString value;
    QString unit;
};
struct CStepFile
{
    QString name;
    QString desp;
    QString value;
};


struct WorkFlowProperty
{
    QString name;
    QString desp;
    QString type;
};
struct WorkFlowParam
{
    QString m_author;
    QDateTime dtCreateTime;
    QString m_strLocation;
};

struct CPortProperty
{
    enum LOCATION{
        TOP,
        BOTTOM,
        LEFT,
        RIGHT
    };
    QString name;
    QString refers;
    QString direction;
    LOCATION location = TOP;
    CPortProperty(){}
    CPortProperty(QString _name,QString _refers,QString _direction,LOCATION _location)
        :name(_name),refers(_refers),direction(_direction),location(_location)
    {

    }

};

class CPort:public QObject
{
    Q_OBJECT

    CPortProperty* property = nullptr;
    QPointF pos;
    std::list<QString> m_listFiles;
    friend class WorkFlowXML;
public:
    explicit CPort(CPortProperty* _property,QObject* parent = nullptr);
    ~CPort();
    QPointF getPos() const;
    void setPos(const QPointF &value);

    CPortProperty *getProperty() const;
    void setProperty(CPortProperty *value);

    void addFlie(QString filePath);;
    void deleteFile(QString filePath);

signals:
    void posChange();
    void updatePos();

};

class CRelation: public QObject
{
    Q_OBJECT

    CRelationProperty* property=nullptr;
    CPort* m_srcPort=nullptr;
    CPort* m_dstPort=nullptr;
    friend class WorkFlowXML;


public:
    CRelation(QObject* parent = nullptr);
    CRelation(CRelationProperty* _property,CPort* _m_strPort, CPort* _m_dstPort,QObject* parent = nullptr);
    ~CRelation();

    CPort *srcPort() const;
    void setSrcPort(CPort *srcPort);
    CPort *dstPort() const;
    void setDstPort(CPort *dstPort);
    CRelationProperty *getProperty() const;
    void setProperty(CRelationProperty *value);
};

class CAction
{
    CActionProperty* property = nullptr;
    std::list<CActionParam*>m_listPortsParams;
    //std::list<CActionParam*>m_listNormalParams;
    friend class WorkFlowXML;
public:
    CAction(CActionProperty* _property);
    ~CAction();
    CActionProperty *getProperty() const;
    void setProperty(CActionProperty *value);

    void addPortsParams(CActionParam* param);

};

class CStep: public QObject
{
    Q_OBJECT

    CStepProperty*  property=nullptr;
    std::list<CAction*>m_listAction;
    std::list<CStepParam*>m_listParam;
    std::list<CStepFile*>m_listFile;
    std::list<CPort*> m_listPort;


    friend class WorkFlowXML;
    friend class DiagramScene;
    friend class WorkFlow;

public:
    CStep(CStepProperty*  _property,QObject* parent = nullptr);
    ~CStep();
    void addParam(CStepParam* param);
    void deleteParam(CStepParam* param);
    void addAction(CAction* action);;
    void deleteAction(CAction* action);
    void addFile(CStepFile* file);;
    void deleteFile(CStepFile* file);
    void addPort(CPort* port);;
    void deletePort(CPort* port);
    CStepProperty *getProperty() const;
    void setProperty(CStepProperty *value);


    void getListPort(std::list<CPort *>& _list);

    CPort* findCPortByName(const QString& name);
    QPointF getPos() const;
    void setPos(const QPointF &value);
};

class CLink
{
    CPort* m_port=nullptr;
    CRelation* m_relation=nullptr;
    friend class WorkFlowXML;
public:
    CLink(){};
    CLink(CPort* _port,CRelation* _relation);;
    ~CLink();

    CPort *port() const;
    void setPort(CPort *port);
    CRelation *relation() const;
    void setRelation(CRelation *relation);

};

class WorkFlow
{
    WorkFlowProperty*  property=nullptr;
    WorkFlowParam*  param=nullptr;
    std::list<CStep*> m_listStep;
    std::list<CRelation*> m_listRelations;
    std::list<CLink*> m_listLinks;
    friend class WorkFlowXML;
    friend class DiagramScene;

public:

    ~WorkFlow();
    WorkFlow(WorkFlowProperty*  _property);
//    void setParam(QString _m_author,QDateTime _dtCreateTime,QString _m_strLocation);
    void addStep(CStep* step);
    void deleteStep(CStep* step);
    void addRelation(CRelation* step);
    void deleteRelation(CRelation* step);
    void addLink(CLink* step);
    void delteLink(CLink* step);
    bool containCport(CPort* port);

    WorkFlowProperty *getProperty() const;
    void setProperty(WorkFlowProperty *value);
    WorkFlowParam *getParam() const;
    void setParam(WorkFlowParam *value);
    std::list<CStep *> getListStep() const;

    void removeCRelationContainCPort(CPort* cport);
    void removeCRelationAndCLink(CRelation* crelation);

    CPort* findCPortByName(const QString& name);
    CRelation* findCRelationByName(const QString& name);

    std::list<CLink *> getListLinks() const;
};
class WorkFlowXML
{
public:
    static void toXML(WorkFlow* workFlow);
    static WorkFlow* toWorkFlow(QString xmlFile);
    static bool CheckWFIntegrity(WorkFlow* workFlow);

};



#endif // WORKFLOWXML_H
